﻿using AutoMapper;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using YaAppoint.DapperRepositories;
using YaAppoint.Response;

namespace YaAppoint.ApplyDepartments
{
    [RemoteService(isEnabled: false)]
    public class ApplyDepartmentAppService(IRepository<ApplyDepartment, Guid> applyDepartmentRepository,
                                           IDapperApplyDepartmentRepository dapperApplyDepartmentRepository,
                                           IConfiguration configuration,
                                           IDataFilter dataFilter,
                                           AsyncQueryableExecuter queryableExecuter,
                                           IMapper mapper) : ApplicationService, IApplyDepartmentAppService, ITransientDependency
    {
        private readonly IMapper _mapper = mapper;
        private readonly AsyncQueryableExecuter _queryableExecuter = queryableExecuter;
        private readonly IRepository<ApplyDepartment, Guid> _applyDepartmentRepository = applyDepartmentRepository;
        private readonly IDapperApplyDepartmentRepository _dapperApplyDepartmentRepository = dapperApplyDepartmentRepository;
        private readonly IConfiguration _configuration = configuration;
        private readonly IDataFilter _dataFilter = dataFilter;

        /// <summary>
        /// 获取列表
        /// </summary>
        public async Task<BackJson> GetList(string? filterName)
        {
            var query = await _applyDepartmentRepository.GetQueryableAsync();
            if (!string.IsNullOrEmpty(filterName))
            {
                query = query.Where(x => x.Name.Contains(filterName) || x.OuterCode.Equals(filterName));
            }
            query = query.OrderByDescending(x => x.Order).ThenBy(x => x.CreationTime);
            var list = await _queryableExecuter.ToListAsync(query);
            return new BackJson()
            {
                code = 0,
                data = _mapper.Map<List<ApplyDepartment>, List<ApplyDepartmentDto>>(list)
            };
        }

        /// <summary>
        /// 提交新建
        /// </summary>
        public async Task<BackJson> SubmitCreate(CreateApplyDepartmentDto dto)
        {
            var sameEntity = await _applyDepartmentRepository.FirstOrDefaultAsync(x => x.OuterCode.Equals(dto.OuterCode));
            if (sameEntity != null)
            {
                throw new BusinessException(CustomErrorCodes.OuterCodeAlreadyExist)
                {
                    Data =
                    {
                        { "outerCode",dto.OuterCode}
                    }
                };
            }
            var applyDepartmemt = _mapper.Map<CreateApplyDepartmentDto, ApplyDepartment>(dto);
            await _applyDepartmentRepository.InsertAsync(applyDepartmemt);
            return new BackJson()
            {
                code = 0,
                msg = "保存成功。"
            };
        }

        /// <summary>
        /// 提交编辑
        /// </summary>
        public async Task<BackJson> SubmitEdit(ApplyDepartmentDto dto)
        {
            var applyDep = await _applyDepartmentRepository.FirstOrDefaultAsync(x => x.Id == dto.Id);
            if (applyDep == null)
            {
                throw new BusinessException(CustomErrorCodes.ApplyDepartmentNotExist);
            }
            if (dto.OuterCode != applyDep.OuterCode)
            {
                var sameAppDep = await _applyDepartmentRepository.FirstOrDefaultAsync(x => x.OuterCode == dto.OuterCode);
                if (sameAppDep != null)
                {
                    throw new BusinessException(CustomErrorCodes.OuterCodeAlreadyExist);
                }
                applyDep.OuterCode = dto.OuterCode;
            }
            applyDep.Name = dto.Name;
            applyDep.IsActive = dto.IsActive;
            applyDep.Order = dto.Order;
            await _applyDepartmentRepository.UpdateAsync(applyDep);
            return new BackJson()
            {
                code = 0,
                msg = "保存成功。"
            };
        }

        /// <summary>
        /// 删除
        /// </summary>
        public async Task<BackJson> Delete(Guid id)
        {
            List<Guid> list = [id];
            return await DeleteMany(list);
        }

        /// <summary>
        /// 删除多个
        /// </summary>
        public async Task<BackJson> DeleteMany(List<Guid> ids)
        {
            await _applyDepartmentRepository.DeleteManyAsync(ids);
            return new BackJson()
            {
                code = 0,
                msg = "已删除！"
            };
        }

        /// <summary>
        /// 同步数据
        /// </summary>
        public async Task<BackJson> SyncData()
        {
            var list = await _dapperApplyDepartmentRepository.GetListAsync();

            foreach (var dto in list)
            {
                var applyDep = await _applyDepartmentRepository.FirstOrDefaultAsync(x => x.OuterCode == dto.Code && x.InstitutionCode == dto.InstitutionCode);
                if (applyDep != null)
                {
                    applyDep.Name = dto.Name;
                    await _applyDepartmentRepository.UpdateAsync(applyDep);
                }
                else
                {
                    applyDep = new ApplyDepartment();
                    applyDep.Name = dto.Name;
                    applyDep.OuterCode = dto.Code;
                    applyDep.Code = dto.Code;
                    applyDep.IsActive = true;
                    applyDep.InstitutionCode = dto.InstitutionCode;
                    await _applyDepartmentRepository.InsertAsync(applyDep);
                }  
            }
            return new BackJson()
            {
                code = 0,
                msg = "数据同步成功。"
            };
        }

        /// <summary>
        /// 获取详情
        /// </summary>
        public async Task<BackJson> GetDetail(Guid id)
        {
            var applyDep = await _applyDepartmentRepository.FirstOrDefaultAsync(x => x.Id == id);
            if (applyDep == null)
            {
                throw new BusinessException(CustomErrorCodes.ApplyDepartmentNotExist);
            }
            return new BackJson()
            {
                code = 0,
                data = _mapper.Map<ApplyDepartment, ApplyDepartmentDto>(applyDep)
            };
        }
    }
}
